import './index.less';

import { Button, Image, Upload } from 'antd';
import { PlusOutlined, UploadOutlined } from '@ant-design/icons';
import { RcFile, UploadChangeParam } from 'antd/es/upload/interface';
import React, { ReactElement, useCallback, useContext, useEffect, useRef, useState } from 'react';
import { UploadFile, UploadProps } from 'antd/es/upload/interface';
import lodash, { omit } from 'lodash';

import { GalleryItem } from 'lightgallery/lg-utils';
import { InitDetail } from 'lightgallery/lg-events';
import { KfQuickFormContext, valueToArray, isUrl, isVideoUrl, KfTablePickerAction } from 'kf-web-library';
import LightGallery from 'lightgallery/react';
import classNames from 'classnames';
import lgFullscreen from 'lightgallery/plugins/fullscreen';
import lgRotate from 'lightgallery/plugins/rotate';
import lgThumbnail from 'lightgallery/plugins/thumbnail';
import lgVideo from 'lightgallery/plugins/video';
import lgZoom from 'lightgallery/plugins/zoom';
import styled from 'styled-components';
import { useControllableValue } from 'ahooks';
import KfMaterialPicker from '../KfMaterialPicker';
import * as API from '@/services';
import {defaultVideoCoverImgUrl} from "@/constants";
import {MaterialType} from "@/components";

export type UploadValue = string[] | string | undefined;

export interface KfMaterialRapidUploadProps extends Omit<UploadProps, 'multiple' | 'fileList' | 'defaultFileList' | 'value' | 'onRemove' | 'onChange'> {
  value?: UploadValue;
  onChange?: (val: UploadValue) => void;
  readonly?: boolean;

  //单个文件大小限制
  maximumFileSize?: any;

  //展示图片的尺寸(正方形) - (仅 listType 等于 picture 或 picture-card 生效), 默认值 picture-card: 104, picture: 48
  size?: number;
  //是否使用inline方式展示上传列表 (仅 listType 等于 picture 生效)
  pictureUploadlistInline?:
    | boolean
    | {
        width?: number; //宽度, 默认值是200px;
      };
  //是否允许重复的上传文件
  allowRepeatedFile?: boolean;
  //点击后可弹出文件选择框的元素, 默认就是个上传按钮
  triggerElement?: ReactElement | null;

  materialType: MaterialType;
}

type StyledTransientProps = {
  $pictureUploadlistInlineWidth: number;
  $compSize: number;
};

const UploadContainer = styled(Upload)<StyledTransientProps>`
  &.kf-upload-list-picture-inline .ant-upload-list-item {
    float: left;
    width: ${(props) => `${props.$pictureUploadlistInlineWidth}px`};
    margin-right: 8px;
  }

  .ant-upload-list-picture-card-container {
    width: ${(props) => `${props.$compSize}px`};
    height: ${(props) => `${props.$compSize}px`};
  }

  .ant-upload.ant-upload-select-picture-card {
    width: ${(props) => `${props.$compSize}px`};
    height: ${(props) => `${props.$compSize}px`};
  }

  .ant-upload-list-picture .ant-upload-list-item-thumbnail {
    width: ${(props) => `${props.$compSize}px`};
    height: ${(props) => `${props.$compSize}px`};
  }
`;

const KfMaterialRapidUpload: React.FC<KfMaterialRapidUploadProps> = (props) => {
  const { readonly: formReadonly } = useContext(KfQuickFormContext);
  const {
    materialType,
    action = API.UPLOAD_FILE_API_PATH,
    name = 'uploadFile',
    triggerElement: compTriggerElement,
    pictureUploadlistInline = false,
    size: compSize,
    maximumFileSize = 100,
    listType,
    maxCount = 100,
    className: compClassName,
    readonly: compReadonly = false,
    disabled: compDisabled = false,
    allowRepeatedFile = true,
    beforeUpload: antdBeforeUpload,
    children: compChildren,
    ...compRest
  } = props;
  const readonly = formReadonly || compReadonly || compDisabled;

  const materialPickerRef = useRef<KfTablePickerAction<any,any>>();

  let triggerElement =
    compTriggerElement === undefined ? (
      listType === 'picture-card' ? (
        <div>
          <PlusOutlined />
          <div className="ant-upload-text">上传</div>
        </div>
      ) : (
        <Button size={'small'}>
          <UploadOutlined /> 点我上传
        </Button>
      )
    ) : (
      compTriggerElement
    );

  if (triggerElement !== null) {
    triggerElement = (
      <div className={'ant-upload-trigger-element-wrap'} onClick={() => materialPickerRef.current && materialPickerRef.current?.openTablePickerModel()}>
        {triggerElement}
      </div>
    );
  }

  //console.log("compTriggerElement", compTriggerElement)
  //console.log("triggerElement", triggerElement)

  const antdUploadProps = omit(compRest, nameof.toArray(props.value, props.onChange));

  const [compValue, setCompValue] = useControllableValue<UploadValue>(props, {
    defaultValue: undefined,
    valuePropName: 'value',
    trigger: 'onChange',
  });

  const [compFileList, setCompFileList] = useState<UploadFile[]>([]);
  const [galleryItems, setGalleryItems] = useState<GalleryItem[]>([]);

  const setCompFileListAndGalleryItems = (fileList: UploadFile[]) => {
    setCompFileList(fileList);
    setGalleryItems(
      fileList.map((f) => {
        let galleryItem = {
          id: f.uid,
          src: f.url,
          thumb: f.thumbUrl || f.url,
          subHtml: `<div class="lightGallery-captions"><h4>${f.name}</h4></div>`,
        };
        if (isVideoUrl(f.url!)) {
          galleryItem = {
            ...galleryItem,
            src: undefined,
            thumb: defaultVideoCoverImgUrl,
            video: {
              source: [
                {
                  src: f.url!,
                  type: 'video/mp4',
                },
              ],
              attributes: { preload: false, controls: true },
            },
          } as any;
        }
        return galleryItem;
      }),
    );
  };

  //监听value, 变换为fileList
  useEffect(() => {
    //过滤掉重复的
    const fileUrlList = lodash.uniq(valueToArray(compValue) as string[]);
    let fileList = fileUrlList.map((rawUrl, rawUrlIndex) => {
      if (!isUrl(rawUrl)) {
        rawUrl = 'http://invaild.img/please_delete_it.png?originalFilename=please_delete_it.png';
      }
      const url = new URL(rawUrl);
      const searchParams = url.searchParams;
      //展示文件名要么从参数从获取, 要不就使用 url最后的一段
      const filename = searchParams.get('originalFilename') || url.pathname.split('/').pop();
      const thumbWidth = listType !== 'picture-card' ? 50 : 86;

      let thumbUrl = `${url.origin}${url.pathname}?w=${thumbWidth}&h=${thumbWidth}`;
      //视频的默认封面
      if (isVideoUrl(rawUrl)) {
        thumbUrl = defaultVideoCoverImgUrl;
      }

      //先从当前的fileList中看下是否已存在了, 如果有就用存在的盖住
      const existUploadFile = compFileList.find((f) => (f.url || f.response?.data[0]) === rawUrl);
      return {
        uid: `${rawUrl}`,
        name: filename,
        status: 'done',
        ...existUploadFile,
        url: rawUrl,
        thumbUrl,
      } as UploadFile;
    });

    if (fileList.length >= maxCount) {
      fileList = fileList.slice(-maxCount);
    }
    setCompFileListAndGalleryItems(fileList);
  }, [compValue]);

  const getUploadFileUrl = (file: UploadFile): string => {
    return file.url || (file.response?.data[0] as string);
  };

  // 根据maxCount来判断触发prop.onChange时 给数组还是单值
  const intelligentSetCompValue = (files: UploadFile[]) => {
    const valArr = files.map((f) => getUploadFileUrl(f));
    setCompValue(maxCount > 1 ? valArr : valArr.length > 0 ? valArr[0] : undefined);
  };

  const beforeUpload = (file: RcFile, fileList: RcFile[]) => {
    if (antdBeforeUpload) {
      return antdBeforeUpload(file, fileList);
    }
    return true;
  };

  const onRemove = (file: UploadFile) => {
    intelligentSetCompValue(compFileList.filter((f) => f.uid !== file.uid));
  };

  const onChange = ({ file, fileList, event }: UploadChangeParam<UploadFile>) => {
    //只有所有文件都上传完了, 才触发prop.onChange
    if (file.status === 'done') {
      if (allowRepeatedFile) {
        //如果允许上传重复的文件就在url后面追加个时间戳, 这样在监听value, 变换为fileList时就不会被过滤掉了
        file.url = getUploadFileUrl(file) + '&_d=' + Date.now();
      }
      setCompFileListAndGalleryItems(fileList);
      if (fileList.filter((f) => f.status === 'done').length === fileList.length) {
        intelligentSetCompValue(fileList);
      }
    } else {
      setCompFileListAndGalleryItems(fileList);
    }
  };

  let pictureUploadlistInlineWidth = 200;
  if (typeof pictureUploadlistInline === 'object') {
    pictureUploadlistInlineWidth = pictureUploadlistInline.width ?? 200;
  }
  let enabledPictureUploadlistInline = false;
  if (pictureUploadlistInline && listType === 'picture') {
    enabledPictureUploadlistInline = true;
  }

  //$开头代表是 Transient props (styled-components v5.1新增), styled-components框架会自动过滤掉,不会传递给React组件,不是标准dom的属性名输出到html中会报错
  const styledTransient: StyledTransientProps = {
    $pictureUploadlistInlineWidth: pictureUploadlistInlineWidth,
    // 默认值 picture-card: 104, picture: 48
    $compSize: compSize ?? (listType === 'picture' ? 48 : 104),
  };

  /**
   * 自定义预览
   */
  const lightGallery = useRef<any>(null);
  const openGallery = (file: UploadFile) => {
    const fileIndex = compFileList.filter((f) => f.status === 'done').findIndex((t) => t.uid === file.uid);
    lightGallery.current.refresh(galleryItems);
    lightGallery.current.openGallery(fileIndex === -1 ? 0 : fileIndex);
  };
  const onGalleryInit = useCallback((detail: InitDetail) => {
    if (detail) {
      lightGallery.current = detail.instance;
    }
  }, []);

  return (
    <>
      <UploadContainer
        {...antdUploadProps}
        name={name}
        multiple={maxCount > 1}
        maxCount={maxCount}
        disabled={readonly}
        fileList={[...compFileList]}
        beforeUpload={beforeUpload}
        onChange={onChange}
        onRemove={onRemove}
        onPreview={openGallery}
        listType={listType}
        action={action}
        className={classNames(compClassName, { 'kf-upload-list-picture-inline': enabledPictureUploadlistInline })}
        openFileDialogOnClick={false}
        {...styledTransient}
      >
        {
          //非只读, 展示默认的上传按钮
          !readonly ? triggerElement : null
        }
      </UploadContainer>

      <KfMaterialPicker
        type={materialType}
        tablePickerResultVisible={false}
        multiple={maxCount > 1}
        entityInValue={true}
        actionRef={materialPickerRef}
        onChange={(mVal) => {
          const materials = valueToArray(mVal) as API.Material[];

          setCompValue(maxCount > 1 ? materials.map((m) => m.url!) : materials.length > 0 ? materials[0].url : undefined);
        }}
      />

      {/*自定义预览*/}
      <LightGallery
        elementClassNames="custom-classname"
        dynamic={true}
        thumbnail={true}
        //rotate={true}
        licenseKey={'0000-0000-0000-0000'}
        dynamicEl={galleryItems}
        onInit={onGalleryInit}
        plugins={[lgZoom, lgVideo, lgThumbnail, lgRotate, lgFullscreen]}
      />
    </>
  );
};

export default KfMaterialRapidUpload;
